using System;
using System.Text;
using csammisrun.OscarLib.Utility;

namespace csammisrun.OscarLib
{
  /// <summary>
  /// Provides a callback function for informational messages sent by the OSCAR library
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="message">A status message</param>
  public delegate void InformationMessageHandler(Session sess, string message);

  /// <summary>
  /// Provides a callback function for warning messages sent by the OSCAR library
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="message">A warning message</param>
  /// <remarks>
  /// Messages received on this event are non-fatal errors, the session will continue
  /// </remarks>
  public delegate void WarningMessageHandler(Session sess, ServerErrorCode errorcode);

  /// <summary>
  /// Provides a callback function for error messages sent by the OSCAR library
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="message">An error message</param>
  /// <remarks>
  /// Messages received on this event are fatal, and the session will end
  /// </remarks>
  public delegate void ErrorMessageHandler(Session sess, ServerErrorCode errorcode);

  /// <summary>
  /// Provides a callback function for typing notifications sent by the server
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="screenname">The screen name sending the typing notification</param>
  /// <param name="notification">The typing notification being sent</param>
  public delegate void TypingNotificationHandler(Session sess, string screenname, TypingNotification notification);

  /// <summary>
  /// Provides a callback function for warning acknowledgements sent by the server
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="screenname">The screenname of the remote client</param>
  /// <param name="WarningLevelGain">The remote client's rise in warning level</param>
  /// <param name="NewWarningLevel">The remote client's new warning level</param>
  public delegate void WarningAcknowledgementHandler(
    Session sess, string screenname, ushort WarningLevelGain, ushort NewWarningLevel);

  /// <summary>
  /// Provides a callback function to be called when the login sequence is completed
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  public delegate void LoginCompletedHandler(Session sess);

  /// <summary>
  /// Provides a callback function to be called during the login sequence to alert the user
  /// of positive progress
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="message">A status message</param>
  /// <param name="percentdone">The percentage of the login progress that has been completed</param>
  public delegate void LoginStatusUpdateHandler(Session sess, string message, double percentdone);

  #region SNAC17 delegates
  /// <summary>
  /// Provides a callback function to be called if the login sequence fails
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="errorcode">A description of the failure</param>
  public delegate void LoginFailedHandler(Session sess, LoginErrorCode errorcode);
  #endregion

  /// <summary>
  /// Provides a callback function for receiving ICBM messages sent by the server
  /// </summary>
  /// <param name="message">The <see cref="IM"/> that was received</param>
  public delegate void MessageReceivedHandler(Session sess, IM message);

  /// <summary>
  /// Provides a callback function for receiving file transfer requests
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="sender">The <see cref="UserInfo"/> of the client requesting the transfer</param>
  /// <param name="IP">The verified IP address of the remote client</param>
  /// <param name="filename">The name of the file the remote client is attempting to send</param>
  /// <param name="filesize">The size of the file, in bytes</param>
  /// <param name="message">The message received with the file transfer request</param>
  /// <param name="key">The unique key needed to respond to this request</param>
  public delegate void FileTransferRequestReceivedHandler(
    Session sess, UserInfo sender, string IP, string filename, uint filesize, string message, byte[] key);

  /// <summary>
  /// Provides a callback function for receiving Direct IM transfer requests
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="sender">The <see cref="UserInfo"/> of the client requesting the transfer</param>
  public delegate void DirectIMRequestReceivedHandler(Session sess, UserInfo sender);

  /// <summary>
  /// Provides a callback function for querying a user's information
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="info">A <see cref="UserInfoResponse"/> structure describing the user</param>
  public delegate void UserInfoReceivedHandler(Session sess, UserInfoResponse info);

  /// <summary>
  /// Provides a callback function for receiving a user status notification from the server
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="userinfo">A <see cref="UserInfo"/> block describing the user</param>
  public delegate void UserStatusReceivedHandler(Session sess, UserInfo userinfo);

  /// <summary>
  /// Provides a callback function for receiving search by email results from the server
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="email">The email address that was searched for</param>
  /// <param name="results">The screennames that are associated with the email address</param>
  public delegate void SearchByEmailResultsHandler(Session sess, string email, string[] results);

  /// <summary>
  /// Provides a callback function for receiving popup messages from the server
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="width">The width of the popup box, in pixels</param>
  /// <param name="height">The height of the popup box, in pixels</param>
  /// <param name="delay">The autohide delay of the popup box, in seconds</param>
  /// <param name="url">The URL associated with the message</param>
  /// <param name="message">The message to display</param>
  public delegate void PopupMessageHandler(Session sess, int width, int height, int delay, string url, string message);

  /// <summary>
  /// Provides a callback function for undeliverable message notices from the server
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="channel">The channel of the message</param>
  /// <param name="userinfo">A <see cref="UserInfo"/> block describing the sender</param>
  /// <param name="numbermissed">The number of missed message from this sender</param>
  /// <param name="reason">A <see cref="UndeliverableMessageReason"/> describing the reason for failure</param>
  public delegate void UndeliverableMessageHandler(
    Session sess,
    ushort channel,
    UserInfo userinfo,
    ushort numbermissed,
    UndeliverableMessageReason reason);

  /// <summary>
  /// Provides a callback function for message accepted notifications from the server
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="channel">The channel of the message</param>
  /// <param name="screenname">The screenname to which the message was sent</param>
  public delegate void MessageAcceptedHandler(Session sess, ushort channel, string screenname);

  #region SNAC0F delegates
  /// <summary>
  /// Provides a callback function for directory search results sent by the server
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="results">The results of the directory search</param>
  public delegate void SearchResultsHandler(Session sess, DirectoryEntry[] results);

  /// <summary>
  /// Provides a callback function for getting a list of interest items
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="results">The results of the interests request</param>
  public delegate void InterestsReceivedHandler(Session sess, InterestItem[] results);
  #endregion

  /// <summary>
  /// Provides a callback function for receiving user offline notifications
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="userinfo">A <see cref="UserInfo"/> block describing the user</param>
  public delegate void UserOfflineHandler(Session sess, UserInfo userinfo);

  #region SNAC13 delegates
  /// <summary>
  /// Provides a callback function for notifiying the client once the SSI list has been sent
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  public delegate void ContactListFinishedHandler(Session sess);

  /// <summary>
  /// Provides a callback function for receiving a new buddy item at signon
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="buddy">An <see cref="SSIBuddy"/> object</param>
  public delegate void BuddyItemReceivedHandler(Session sess, SSIBuddy buddy);

  /// <summary>
  /// Provides a callback function for receiving a new group item at signon
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="group">An <see cref="SSIGroup"/>"/> object</param>
  /// <param name="index">The index of the group</param>
  public delegate void GroupItemReceivedHandler(Session sess, SSIGroup group);

  /// <summary>
  /// Provides a callback function for receiving a master group item at signon
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="numgroups">The number of groups</param>
  public delegate void MasterGroupItemReceivedHandler(Session sess, int numgroups);

  /// <summary>
  /// Provides a callback function to alert the client when an SSI edit is complete
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  public delegate void SSIEditCompleteHandler(Session sess);

  #endregion

  /// <summary>
  /// Provides a callback function for receiving a warning notification
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="newlevel">The client's new warning level</param>
  /// <param name="anonymous"><c>true</c> if this warning was sent anonymously, <c>false</c> otherwise</param>
  /// <param name="ui">A <see cref="UserInfo"/> structure describing the warning user. If <paramref name="anonymous"/> is
  /// <c>true</c>, this structure is unpopulated</param>
  public delegate void WarningReceivedHandler(Session sess, ushort newlevel, bool anonymous, UserInfo ui);

  /// <summary>
  /// Provides a callback function for receiving the MOTD from the server at signon
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="motdtype">The type of the MOTD</param>
  /// <param name="message">The message string</param>
  public delegate void MessageOfTheDayReceivedHandler(Session sess, ushort motdtype, string message);

  /// <summary>
  /// Provides a callback function for receiving directory update acknowledgements
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="success"><c>true</c> if the directory update succeded, and <c>false</c> otherwise</param>
  public delegate void DirectoryUpdateAcknowledgedHandler(Session sess, bool success);

  /// <summary>
  /// Provides a callback function for receiving status report intervals from the server
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="hours">The minimum status reporting interval, in hours</param>
  public delegate void ReportingIntervalReceivedHandler(Session sess, int hours);

  /// <summary>
  /// Provides a callback function for tracking the progress of a file transfer
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="filename">The rendezvous cookie belonging to the file being transfered</param>
  /// <param name="BytesTransfered">The number of bytes transfered so far</param>
  /// <param name="BytesTotal">The total number of bytes to be transfered</param>
  public delegate void FileTransferProgressHandler(Session sess,
    byte[] cookie,
    uint BytesTransfered,
    uint BytesTotal);

  /// <summary>
  /// Provides a callback function for receiving notification of a cancelled transfer
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="filename">The rendezvous cookie belonging to the cancelled file</param>
  /// <param name="reason">The reason for the cancellation</param>
  public delegate void FileTransferCancelledHandler(Session sess,
    byte[] cookie,
    string reason);

  /// <summary>
  /// Provides a callback function for receiving notification of a completed transfer
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="filename">The rendezvous cookie belonging to the completed file</param>
  public delegate void FileTransferCompletedHandler(Session sess, byte[] cookie);

  /// <summary>
  /// Provides a callback function for receiving DirectIMs sent by a remote user
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="message">A <see cref="DirectIM"/> message</param>
  public delegate void DirectIMReceivedHandler(Session sess, DirectIM message);

  #region SNAC10 delegates
  /// <summary>
  /// Provides a callback function for receiving a buddy icon from the server
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="screenname">The screenname who owns the received icon</param>
  /// <param name="iconstream">A <see cref="System.IO.Stream"/> containing the received image</param>
  public delegate void BuddyIconDownloadCompletedHandler(Session sess, string screenname,
    System.IO.Stream iconstream);

  /// <summary>
  /// Provides a callback function for notification of icon download failure
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="screenname">The screenname of the attemped icon download</param>
  /// <param name="reason">The reason for the failure</param>
  public delegate void BuddyIconDownloadFailedHandler(Session sess, string screenname, string reason);

  /// <summary>
  /// Provides a callback function for notification of successful icon upload
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  public delegate void BuddyIconUploadCompletedHandler(Session sess);

  /// <summary>
  /// Provides a callback function for notification of icon upload failure
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="reason">The reason for the failure</param>
  public delegate void BuddyIconUploadFailedHandler(Session sess, string reason);
  #endregion

  #region Chat room delegates
  /// <summary>
  /// Provides a callback function for notification of successful chat room creation
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="newroom">A <see cref="ChatRoomInfo"/> object representing the new room</param>
  public delegate void ChatRoomCreatedHandler(Session sess, ChatRoomInfo newroom);

  /// <summary>
  /// Provides a callback function for receiving chat room invitations
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="sender">A <see cref="UserInfo"/> object describing the inviter</param>
  /// <param name="roomname">The name of the chatroom</param>
  /// <param name="message">An invitation chatroom</param>
  /// <param name="encoding">The text encoding used in the chatroom</param>
  /// <param name="language">The language used in the chatroom</param>
  /// <param name="key">The unique key needed to respond to this request</param>
  public delegate void ChatInvitationReceivedHandler(Session sess, UserInfo sender, string roomname, 
    string message, Encoding encoding, string language, byte[] key);

  /// <summary>
  /// Provides a callback function for receiving a message in a chat room
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="room">A <see cref="ChatRoomInfo"/> object</param>
  /// <param name="sender">A <see cref="UserInfo"/> object describing the user who sent the message</param>
  /// <param name="message">The message that was sent</param>
  /// <param name="encoding">The text encoding of the message</param>
  /// <param name="language">The language of the message</param>
  public delegate void ChatRoomMessageReceivedHandler(Session sess,
    ChatRoomInfo room, UserInfo sender,
    string message, Encoding encoding, string language);

  /// <summary>
  /// Provides a callback function for receiving "User Joined Chat Room" reports
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="room">A <see cref="ChatRoomInfo"/> object</param>
  /// <param name="ui">A <see cref="UserInfo"/> block describing the user</param>
  public delegate void ChatRoomUserJoinedHandler(Session sess, ChatRoomInfo room, UserInfo ui);

  /// <summary>
  /// Provides a callback function for receiving "User Left Chat Room" reports
  /// </summary>
  /// <param name="sess">The <see cref="Session"/> object raising the event</param>
  /// <param name="room">A <see cref="ChatRoomInfo"/> object</param>
  /// <param name="ui">A <see cref="UserInfo"/> block describing the user</param>
  public delegate void ChatRoomUserLeftHandler(Session sess, ChatRoomInfo room, UserInfo ui);
  #endregion

  internal delegate void ProxiedSocketFactoryResultHandler(System.Net.Sockets.Socket socket, string errormsg);

  /// <summary>
  /// Provides a factory function for connecting sockets through a proxy
  /// </summary>
  /// <param name="host">The host to which to connect</param>
  /// <param name="port">The port on the host to which to connect</param>
  /// <param name="callback">A callback in which to receive the socket and, potentially, an error message.</param>
  /// <returns>A TCP stream socket ready to send and receive data</returns>
  /// <remarks>
  /// <para>This delegate is intended to be used if OscarLib is part of an application that provides a global
  /// socket connection factory through various proxies.</para>
  /// <para>The <paramref name="callback"/> parameter must be a delegate that accepts a Socket and a string as its parameters.</para>
  /// </remarks>
  public delegate void ProxiedSocketFactoryDelegate(string host, int port, Delegate callback);
}
